package com.example.understandvideo.service;

import com.example.understandvideo.mapper.AnalysisTaskDao;
import com.example.understandvideo.mapper.AsrTaskDao;
import com.example.understandvideo.mapper.SettingDao;
import com.example.understandvideo.pojo.AnalysisTask;
import com.example.understandvideo.pojo.AsrTask;
import com.example.understandvideo.pojo.TaskRequest;
import com.example.understandvideo.pojo.request.TaskCreateRequest;
import com.example.understandvideo.pojo.response.CommonResponse;
import com.example.understandvideo.pojo.response.TaskDetailResponse;
import com.example.understandvideo.tool.Tools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class DemoProcessor {

    private final BlockingQueue<AnalysisTask> queue = new LinkedBlockingQueue<>(100);
    private volatile boolean running = true;
    private final int THREAD_COUNT = 10;
    @Resource
    private DemoService demoService;
    @Resource
    private AnalysisTaskDao analysisTaskDao;
    @Resource
    private AsrTaskDao asrTaskDao;
    @Resource
    private SettingDao settingDao;

    @Resource
    private VoiceProcessor voiceProcessor;

    /**
     * 创建线程池，核心10，最大核心30，存活5秒，队列存储2000，拒绝策略直接抛出异常
     */
    private final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(THREAD_COUNT, 30,
            5, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100),
            new ThreadPoolExecutor.CallerRunsPolicy());

    public DemoProcessor() {
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.execute(new ResultWorker());
        }
    }

    String getWorkSpace() {
        String os = System.getProperty("os.name");
        if (os != null && !os.toLowerCase().startsWith("windows")) {
            return settingDao.selectByPrimaryKey(2L);
        } else {
            return settingDao.selectByPrimaryKey(1L);
        }
    }

    public CommonResponse list(TaskRequest request) {
        if (Objects.isNull(request) || Objects.isNull(request.getPage()) || Objects.isNull(request.getPageSize())) {
            request.setPage(0);
            request.setPageSize(10);
        }
        Long count = analysisTaskDao.count(request);
        if (Objects.isNull(count) || count == 0) {
            return new CommonResponse();
        }
        List<AnalysisTask> responseList = analysisTaskDao.search(request);
        if (Objects.isNull(responseList)) {
            return new CommonResponse();
        }
        CommonResponse<AnalysisTask> response = new CommonResponse();
        response.setTotal(count);
        response.setResponseList(responseList);
        return response;
    }

    public TaskDetailResponse detail(Long id) {
        AnalysisTask task = analysisTaskDao.selectByPrimaryKey(id);
        TaskDetailResponse response = new TaskDetailResponse();
        response.setName(task.getName());
        response.setFilepath(task.getFilepath());
        AsrTask asrTask = asrTaskDao.selectByPid(id);
        if(Objects.nonNull(asrTask) && Objects.nonNull(asrTask.getContent())){
            response.setAsrText(asrTask.getContent());
        }
        response.setResult(task.getResult());
        response.setTotalTaskId(task.getTotalTaskId());
        return response;
    }

    public void put(MultipartFile multipartFile, String tag) {
        try {
            String suffixName = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf('.'));
            String filename = multipartFile.getOriginalFilename().substring(0, multipartFile.getOriginalFilename().lastIndexOf('.'));
            AnalysisTask analysisTask = new AnalysisTask();
            String uuid = Tools.getUUID();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Date now = new Date();
            String nowDay = format.format(now);
            File file = new File(getWorkSpace() + File.separator + nowDay + File.separator + uuid + suffixName);
            try {
                // 确保父目录存在
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                file.createNewFile();
                multipartFile.transferTo(file);
            } catch (Exception e) {
                e.printStackTrace();
            }
            analysisTask.setName(filename);
            analysisTask.setCreateTime(new Date());
            analysisTask.setFilepath(file.getAbsolutePath());
            analysisTask.setStatus(0);
            analysisTask.setUpdateTime(new Date());
            analysisTask.setTag(tag);
            analysisTaskDao.insert(analysisTask);
            this.queue.put(analysisTask);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void put(String name, String filepath, String tag, Long pid) {
        try {
            AnalysisTask analysisTask = new AnalysisTask();
            analysisTask.setName(name);
            analysisTask.setTotalTaskId(pid);
            analysisTask.setCreateTime(new Date());
            analysisTask.setFilepath(filepath);
            analysisTask.setStatus(0);
            analysisTask.setUpdateTime(new Date());
            analysisTask.setTag(tag);
            analysisTaskDao.insert(analysisTask);
            this.queue.put(analysisTask);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    @PreDestroy
    public void stop() throws InterruptedException {
        this.running = false;
        //ExecutorUtil.shutdown(threadPool);
    }

    private class ResultWorker implements Runnable {
        @Override
        public void run() {
            try {
                while (running) {
                    AnalysisTask model = queue.take();
                    try {
                        String result = demoService.videoUnderstand(model.getFilepath(), model.getTag());
                        voiceProcessor.putByAnalysis(model.getFilepath(), model.getId());
                        model.setResult(result);
                        model.setStatus(1);
                        model.setUpdateTime(new Date());
                        analysisTaskDao.updateByPrimaryKeySelective(model);
                    } catch (Exception e) {
                        model.setStatus(2);
                        model.setUpdateTime(new Date());
                        analysisTaskDao.updateByPrimaryKeySelective(model);
                        log.error("[FileObjectProcessor] sync data error,errorMsg={}", e.getMessage());
                    }
                }
            } catch (Exception ex) {
                log.error("[FileObjectProcessor] run error={}", ex.getMessage());
            }
        }
    }
}
